/**
 * 
 */
package helpers;

import interfaces.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import automaton.StateImpl;

/**
 * @author LE VAN LINH
 *
 */
public class HandleHashSet extends HashSet<State> {

	/**
	 * 
	 */
	char label;
	
	public char getLabel() {
		return label;
	}

	public void setLabel(char label) {
		this.label = label;
	}

	private static final long serialVersionUID = 707169446042085266L;

	/**
	 * Union of 2 sets
	 * @param set1
	 * @param set2
	 * @return
	 */
	public static HandleHashSet union(HandleHashSet set1, HandleHashSet set2){
		for (State state : set2) {
			set1.add(state);
		}
		return set1;
	}
	
	/**
	 * Intersection of 2 sets
	 * @param set1
	 * @param set2
	 * @return
	 */
	public static HandleHashSet interSection(HandleHashSet set1, HandleHashSet set2){
		HandleHashSet result = new HandleHashSet();
		
		Map<State, Boolean> map = new HashMap<State, Boolean>();
		for (State state : set1) {
			map.put(state, true);
		}
		
		for (State state : set2) {
			if(map.get(state)!=null)
				result.add(state);
		}
		return result;
	}
	
	/**
	 * Subtraction 2 sets
	 * @param set1
	 * @param set2
	 * @return
	 */
	public static HandleHashSet subtraction(HandleHashSet set1, HandleHashSet set2){
		HandleHashSet result = new HandleHashSet();
		
		for (State state : set1) {
			if(!checkStateIntoSet(set2, state))
				result.add(state);
		}
		return result;
	}
	
	/**
	 * Get the set have the smaller size
	 * @param set1
	 * @param set2
	 * @return
	 */
	public static HandleHashSet minimalSet(HandleHashSet set1, HandleHashSet set2){
		return set1.size() > set2.size() ? set2 : set1;
	}
	
	/**
	 * Check state s belongs to set or not
	 * @param set
	 * @param s
	 * @return
	 */
	public static boolean checkStateIntoSet(HandleHashSet set, State s){		
		for (State state : set) {
			if(state.label().toString().compareTo(s.label().toString()) == 0){
				return true;
			}
		}
		return false;
	}
	
	public static HandleHashSet getSameSet(HandleHashSet set, State s){
		HandleHashSet hset = new HandleHashSet ();
		if(set.size()>1)
			hset = set;
		return hset;		
	}
	
	/**
	 * Check Set is subset or not
	 * @param set
	 * @return
	 */
	public boolean subSet(HandleHashSet set){
		boolean result = true;
		for (State state : set) {
			if(this.contains(state)){
				result =false;
				break;
			}
		}
		return result;
	}
	
	/**
	 * Check equatation of two sets
	 */
	@Override
	public boolean equals(Object o) {
		HandleHashSet handle = (HandleHashSet)o;
		if(this.size() == handle.size()){
			if(this.subSet(handle) && handle.subSet(this))
				return true;
		}
		return super.equals(o);
	}	
	
	/**
	 * Composed all states in a class into a state
	 * @param set
	 * @return
	 */
	public static State composedState(HandleHashSet set) {		
		if(set != null){
			String label ="";
			boolean init = false;
			boolean end = false;
			Iterator<State> iterator = set.iterator();
			
			while(iterator.hasNext()){
				State s = iterator.next();
				if(s.label()!= null && s.label()!=""){
					label += s.label().toString();
					if(s.terminal())
						end = true;
					if(s.initial())
						init = true;
				}
				//break;
			}
			return new StateImpl(label, init, end);
		}
		return null;
	}
	
	/**
	 * Get all states of a set
	 * @param set
	 * @return
	 */
	public static ArrayList<State> getStates(HandleHashSet set) {		
		ArrayList<State> states = new ArrayList<State>();
		if(set.size()>0){
			Iterator<State> iterator = set.iterator();
			
			while(iterator.hasNext()){
				State s = iterator.next();
				if(s.label()!= null && s.label()!=""){
					states.add(s);
				}
			}
		}
		return states;		
	}
	
	public static void printString(HandleHashSet set) {
		
		if(set.size()>0){
			Iterator<State> iterator = set.iterator();
			System.out.print("(");
			while(iterator.hasNext()){
				State s = iterator.next();
				System.out.print(s.label() + " ");
			}			
			System.out.print(")");
		}
		System.out.println();
	}
}
